#include <Arduino.h>

const int ntcPin = A0;
const int fanPin = 5; // PD5---0C0B

float Vol;  //检测点电压值
float Rdiv = 10000.0;  //一端串联NTC且另一端接地的分压电阻的阻值
float Kelvin = 273.15;  //开尔文转摄氏度时需要减去的数值
float Rntc;  //当前温度下NTC的阻值
float Rnor = 5000.0;  //NTC在25°C下的阻值
float Bntc = 3950.0;  //热敏电阻(NTC)的重要参数
float T2 = (Kelvin + 25);  //25°C对应的开尔文温标
int Tcelsius;  //当前温度(°C)
const int8_t TempOffset = 1;   //温度补偿(°C)
const uint8_t MinTemp = 45;  //风扇起转温度

int stepNum;

void setup() {
  Serial.begin(9600);

  pinMode(fanPin, OUTPUT);    // DDRD |= (1 << fanPin);
  digitalWrite(fanPin, LOW);    // PORTD &= ~(1 << fanPin);
  TCCR0A = 0;
  TCCR0B = 0;
  // Set Timer0 to 20 kHz Fast PWM mode-7 with prescaler 8
  // OCR0B controls duty cycle
  // 20 kHz = 16000000 / ( 8*(1 + OCR0A)) ==> OCR0A = 99
  TCCR0A |= (1 << WGM01) | (1 << WGM00); //Mode-7 Fast PWM
  TCCR0B |= (1 << WGM02);    //Mode-7 Fast PWM
  
  TCCR0A |= (1 << COM0B1) | (0 << COM0B0);  //Non-invert: HIGH-LOW // PD5---0C0B
  TCCR0B |= (1 << CS01);  //start TC0 with prescaler 8
  OCR0A = 99;
  OCR0B = 0;   // duty cycle
  TCNT0 = 0;
	delay(3000);	// N秒，等待上电稳定
}

void loop() {
    static unsigned int dutyCycle = 0;
    static unsigned int savDuty = 0;

	delay(1000);
    float adcValue = analogRead(ntcPin);
    Vol = (adcValue * 5.0) / 1023.0;
    Rntc = Rdiv * (5.0 - Vol) / Vol;
    Tcelsius = 1 / (log(Rntc/Rnor) / Bntc + 1/T2) - Kelvin + TempOffset;

    if (Tcelsius < MinTemp) {
        dutyCycle = 0;
    } else {
        stepNum = Tcelsius - MinTemp;
        dutyCycle = (unsigned int)map(stepNum, 0, 45, 15, 99);    // * 要映射的数值、输入下限、输入上限、 输出下限、输出上限
    }

    //analogWrite(fanPin, dutyCycle);
    if(dutyCycle > savDuty){
        savDuty = dutyCycle;
    }
    else if(dutyCycle < savDuty){
        if(savDuty > 2){
            savDuty -= 2;
        }
        else{
            savDuty = 0;
        }
        dutyCycle = savDuty;
    }
    OCR0B = dutyCycle;

    Serial.print("adc: ");
    Serial.print(adcValue);
    Serial.print("    ");
    Serial.print("NTC阻值: ");
    Serial.print(Rntc);
    Serial.print("    ");
    Serial.print("温度: ");
    Serial.print(Tcelsius);
    Serial.print("    ");
    Serial.print(" 占空比: ");
    Serial.println(dutyCycle);
    delay(500);
}
